﻿using System.Collections.Generic;
using Metro.Kashikoi.Service.Common.Entity;
using Metro.Kashikoi.Service.Storage.Business;
using Metro.Kashikoi.Service.Storage.Entity;
using Metro.Kashikoi.ServiceContract;
using Metro.Kashikoi.ServiceContract.Item;
using Metro.Kashikoi.ServiceContract.Location;
using Metro.Kashikoi.ServiceContract.Storage;

namespace Metro.Kashikoi.Service.Storage.Service
{
    /// <summary>
    /// This class implements the interface <c>IStorageService</c>.
    /// </summary>
    class StorageService : IStorageService
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LocationService"/> class.
        /// </summary>
        public StorageService()
        {
            this.Facade = new Facade();
            this.Factory = new UnitOfWorkFactory();
        }

        private IItemService ItemService { get { return ServiceBus.GetService<IItemService>(); } }
        private ILocationService LocationService { get { return ServiceBus.GetService<ILocationService>(); } }
        private ICategoryService CategoryService { get { return ServiceBus.GetService<ICategoryService>(); } }

        private IFacade Facade { get; set; }
        private IUnitOfWorkFactory Factory { get; set; }

        #region IStorageService Members

        public BinInventory CreateInventory(BinInventory inventory, int stockAreaId)
        {
            var stockArea = LocationService.GetStockArea(stockAreaId);
            var item = ItemService.GetItem(inventory.ItemId);
            var category = CategoryService.GetCategory(inventory.CategoryId);

            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.CreateInventory(ctx, inventory, stockAreaId);
                ctx.SaveChanges();
            }
            return inventory;
        }

        public void UpdateInventory(BinInventory inventory)
        {
            var stockArea = LocationService.GetStockArea(inventory.StockAreaId);
            var item = ItemService.GetItem(inventory.ItemId);
            var category = CategoryService.GetCategory(inventory.CategoryId);

            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.UpdateInventory(ctx, inventory);
                ctx.SaveChanges();
            }
        }

        public void UpdateInventoriesStockStatus(ICollection<BinInventory> inventories, StockStatus stockStatus)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.UpdateInventoriesStockStatus(ctx, inventories, stockStatus);
                ctx.SaveChanges();
            }
        }

        public void UpdateInventoryStockStatus(string SSID, StockStatus stockStatus)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.UpdateInventoryStockStatus(ctx, SSID, stockStatus);
                ctx.SaveChanges();
            }
        }

        public void DeleteInventory(int inventoryId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.DeleteInventory(ctx, inventoryId);
                ctx.SaveChanges();
            }
        }

        public void DeleteInventoriesOfStockAreas(IEnumerable<int> stockAreaIdList)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.DeleteInventoriesOfStockAreas(ctx, stockAreaIdList);
                ctx.SaveChanges();
            }
        }

        public void DeleteInventoriesOfItems(IEnumerable<int> itemIdList)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                Facade.DeleteInventoriesOfItems(ctx, itemIdList);
                ctx.SaveChanges();
            }
        }

        public IList<BinInventory> GetInventoriesOfStockArea(int stockAreaId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetInventoriesOfStockAreas(ctx, new int[] { stockAreaId });
            }
        }

        public IList<BinInventory> GetInventoriesOfStockAreas(IEnumerable<int> stockAreaIdList)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetInventoriesOfStockAreas(ctx, stockAreaIdList);
            }
        }

        public IList<BinInventory> GetRestockList(IEnumerable<int> stockAreaIdList)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetRestockList(ctx, stockAreaIdList);
            }
        }

        public BinInventory GetInventoryById(int Id)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetInventoryById(ctx, Id);
            }
        }

        public BinInventory GetInventoryBySSID(string SSID)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetInventoryBySSID(ctx, SSID);
            }
        }

        public IList<BinInventory> GetInventoriesByItem(int itemId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                return Facade.GetInventoriesByItem(ctx, itemId);
            }
        }

        public BinInventory CloneInventory(int inventoryId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                var inventory = Facade.CloneInventory(ctx, inventoryId);
                ctx.SaveChanges();
                return inventory;
            }
        }

        public IList<BinInventory> CloneInventoriesOfStockArea(int fromStockAreaId, int toStockAreaId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<IStorageService>())
            {
                var inventories = Facade.CloneInventoriesOfStockArea(ctx, fromStockAreaId, toStockAreaId);
                ctx.SaveChanges();
                return inventories;
            }
        }

        #endregion
    }
}
